package com.ldu.exam.service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javax.transaction.Transactional;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.ldu.exam.assistant.BeanAssistant;
import com.ldu.exam.dao.MenuRepository;
import com.ldu.exam.model.AccountModel;
import com.ldu.exam.model.MenuModel;
import com.ldu.exam.model.RoleModel;

@Service
public class MenuService 
{
	@Autowired
	private MenuRepository repository;

	public Page<MenuModel> findAll(Pageable page) {
		Page<MenuModel> pageList = this.repository.findAll(page);
		this.addParentName(pageList.getContent());
		return pageList;
	}

	public java.util.List<MenuModel> findAll() {
		return this.addParentName(this.repository.findAll());
	}

	public MenuModel find(String id) {
		return this.addParentName(this.repository.findById(id).orElse(null));
	}

	public void delete(String id) {
		this.repository.deleteById(id);
	}

	public MenuModel save(MenuModel model) {
		return this.repository.save(model);
	}

	public Page<MenuModel> findByName(String name, int page, int size) {
		Page<MenuModel> pageList = StringUtils.isEmpty(name) ? this.repository.findAll(PageRequest.of(page, size))
				: this.repository.findByNameContaining(name, PageRequest.of(page, size));
		List<MenuModel> list = this.repository.findAll();
		for (int i = 0; i < pageList.getContent().size(); i++) {
			if (!StringUtils.isEmpty(pageList.getContent().get(i).getParentId())) {
				for (int j = 0; j < list.size(); j++) {
					if (pageList.getContent().get(i).getParentId().equals(list.get(j).getId())) {
						pageList.getContent().get(i).setParentName(list.get(j).getName());
					}
				}
			}
		}
		return pageList;
	}
	
	public Page<MenuModel> findByParentName(String name ,int page, int size)
	{
		Page<MenuModel> pageList = StringUtils.isEmpty(name) ?this.repository.findAll(PageRequest.of(page, size))
				: this.repository.findByParentNameContaining(name, PageRequest.of(page, size));
		List<MenuModel> list = this.repository.findAll();
		for (int i = 0; i < pageList.getContent().size(); i ++)
		{
			if(!StringUtils.isEmpty(pageList.getContent().get(i).getParentId()))
			{
				for (int j = 0; j < list.size(); j++) {
					if (pageList.getContent().get(i).getParentId().equals(list.get(j).getId())) {
						pageList.getContent().get(i).setParentName(list.get(j).getName());
					}
				}
			}
		}
		return pageList;		
	}
	
	public Page<MenuModel> findByAll(String name,String parentName,int page,int size)
	{
		Page<MenuModel> pageList = this.repository.findByNameAndParentNameContaining(name, parentName, PageRequest.of(page, size));
		List<MenuModel> list = this.repository.findAll();
		for (int i = 0; i < pageList.getContent().size(); i++) {
			if (!StringUtils.isEmpty(pageList.getContent().get(i).getParentId())) {
				for (int j = 0; j < list.size(); j++) {
					if (pageList.getContent().get(i).getParentId().equals(list.get(j).getId())) {
						pageList.getContent().get(i).setParentName(list.get(j).getName());
					}
				}
			}
		}
		return pageList;
		
	}
	@Autowired
	private AccountService accountService;

	/**
	 * 查询登录账户所拥有菜单信息
	 * 
	 * @param id 登陆账户ID
	 * @return 登录账户所拥有菜单信息
	 */
	@Cacheable(value = "user:menus", key = "#p0")
	public Set<MenuModel> findAllByRole(String userId) {
		AccountModel account = this.accountService.find(userId);
		Set<RoleModel> roles = account.getRoles();

		if (null == roles || 1 > roles.size())
			return null;

		Set<MenuModel> menus = roles.stream().flatMap(x -> x.getMenus().stream())
				.filter(BeanAssistant.distinctByKey(MenuModel::getId)).filter(x -> !StringUtils.isEmpty(x.getId()))
				.collect(Collectors.toSet());

		return addParentName(menus);
	}

	@Transactional
	public Object update(String id, MenuModel model) {
		model.setId(null);

		MenuModel origin = this.find(id);

		String[] nullPropertyNames = BeanAssistant.getNullPropertyNames(model);

		BeanUtils.copyProperties(model, origin, nullPropertyNames);

		return this.repository.save(origin);
	}

	/**
	 * 往list里注入parentName
	 * 
	 * @param modelList
	 * @return
	 */
	private List<MenuModel> addParentName(List<MenuModel> modelList) {
		for (int i = 0; i < modelList.size(); i++) {
			if (!StringUtils.isEmpty(modelList.get(i).getParentId())) {
				for (int j = 0; j < modelList.size(); j++) {
					if (modelList.get(i).getParentId().equalsIgnoreCase(modelList.get(j).getId())) {
						modelList.get(i).setParentName(modelList.get(j).getName());
					}

				}
			}

		}
		return modelList;

	}

	/**
	 * 往set里注入parentName
	 * 
	 * @param modelSet
	 * @return
	 */
	private Set<MenuModel> addParentName(Set<MenuModel> modelSet) {
		MenuModel modelForOut = new MenuModel();
		Iterator<MenuModel> iteratorForOut = modelSet.iterator();
		List<MenuModel> list = this.repository.findAll();
		while (iteratorForOut.hasNext()) {
			modelForOut = iteratorForOut.next();
			if (!StringUtils.isEmpty(modelForOut.getParentId())) {
				for (int i = 0; i < list.size(); i++) {
					if (list.get(i).getId().equals(modelForOut.getParentId())) {
						modelForOut.setParentName(list.get(i).getName());
					}
				}
			}
		}
		return modelSet;
	}

	/**
	 * 给单个实体注入parentName
	 * 
	 * @param model
	 * @return
	 */
	private MenuModel addParentName(MenuModel model) {
		if (model != null) {
			model.setParentName(this.repository.findById(model.getParentId()).get().getName());
		}
		return model;
	}
	public Object isExit(String name)
	{
		List<MenuModel> list = this.repository.findByName(name);
		if(list.size()>0) {
			return false;
		}else {
			return true;
		}
	}
	public List<MenuModel> findAllNoPage()
	{
		List<MenuModel> list_all = this.repository.findAll();
		List<MenuModel> list_forReturn = new ArrayList<MenuModel>();
		for (MenuModel menuModel : list_all) {
			if(StringUtils.isEmpty(menuModel.getParentId()))
			{
				menuModel.setName(menuModel.getName()+"(一级)");
				list_forReturn.add(menuModel);
				for (MenuModel menuModel2 : list_all) 
				{
					if(menuModel.getId().equalsIgnoreCase(menuModel2.getParentId())) 
					{
						menuModel2.setName(menuModel2.getName()+"(二级)");
						list_forReturn.add(menuModel2);
					}
				}
			}
		}
		return list_forReturn;
	}
	
	public Page<MenuModel> findAllByParentName(String parentName,int page, int size)
	{
		Page<MenuModel> pageList = StringUtils.isEmpty(parentName) ?this.repository.findAll(PageRequest.of(page, size))
				: this.repository.findByParentNameContaining(parentName, PageRequest.of(page, size));
		List<MenuModel> list = this.repository.findAll();
		for (int i = 0; i < pageList.getContent().size(); i ++)
		{
			if(!StringUtils.isEmpty(pageList.getContent().get(i).getParentId()))
			{
				for (int j = 0; j < list.size(); j++) {
					if (pageList.getContent().get(i).getParentId().equals(list.get(j).getId())) {
						pageList.getContent().get(i).setParentName(list.get(j).getName());
					}
				}
			}
		}
		return pageList;	
	}
}
